package core;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.LinkedList;

import core.Room.Type;

public class DlvHandler {
	public Floor floor;
	public AbstractAgent agent;
	public boolean is_as_written;

	public DlvHandler(AbstractAgent agent, Floor floor) {
		this.floor = floor;
		this.agent = agent;
		this.is_as_written = false;
	}

	public void writeInitialPlan(String subgoal) {
		try {
			FileOutputStream file = new FileOutputStream("initial_plan_for_"
					+ subgoal.toUpperCase() + "" + ".plan");

			PrintStream output = new PrintStream(file);

			output.println("always: caused subgoalreached after move(ROOM, CELL), "
					+ "on" + subgoal + "(ROOM, CELL).");

			output.println();
			output.println("noConcurrency.");
			output.println();

			output.print("initially: ");

			// ciccio's position
			output.print("onCiccio(" + this.floor.rooms[this.agent.x].type
					+ ", " + this.agent.y + "). ");

			// objects positions
			for (int i = 0; i < this.floor.rooms.length; i++) {
				for (int j = 0; j < this.floor.rooms[i].squares.length; j++) {

					if (this.floor.rooms[i].squares[j].type != core.Square.Type.Clean
							&& this.floor.rooms[i].squares[j].type != core.Square.Type.Unknown)

						output.print("on" + this.floor.rooms[i].squares[j].type
								+ "(" + this.floor.rooms[i].type + "," + j
								+ "). ");
				}
			}

			// entrance position
			output.print( "onEntrance(" + this.floor.rooms[3].type + "," 
					+ this.floor.doors[3].col + "). ");
			
			output.println();
			output.print("goal: subgoalreached ? (32)");// " + (step_num - 1) + ")");

			output.close();
			file.close();
		} catch (IOException e) {
			System.out
					.println("Error during the generation of the subgoal planning file: "
							+ e);
		}
	}

	/**
	 * Write the answer set program including the position of the rooms and the
	 * doors in the house
	 */
	public void writeDl() {
		if (!is_as_written) {
			try {
				FileOutputStream file = new FileOutputStream("as_program.dl");
				PrintStream output = new PrintStream(file);

				output.println("#maxint=100.");
				output.println();

				for (int i = 0; i < 8; i++)
					output.println("cell(" + i + ").");

				output.println();

				for (int i = 0; i < this.floor.rooms.length; i++) {
					output.println("room(" + this.floor.rooms[i].type + "," + i
							+ ").");
				}

				output.println();

				for (int j = 0; j < this.floor.rooms.length; j++) {
					if (j + 1 < this.floor.rooms.length)
						output.println("door(" + this.floor.rooms[j].type + ","
								+ this.floor.rooms[j + 1].type + ","
								+ this.floor.doors[j].col + ").");
					else
						output.println("door(" + this.floor.rooms[j].type + ","
								+ Type.entrance + "," + this.floor.doors[j].col
								+ ").");
				}
				output.println();

				output.println("door(ROOM1, ROOM2, CELL) :- door(ROOM2, ROOM1, CELL).");

				output.println();

				output.println("adiacentRooms(ROOM1, ROOM2) :- room(ROOM1, ROW1), room(ROOM2, ROW2), ROW1 = ROW2 + 1.");
				output.println("adiacentRooms(ROOM1, ROOM2) :- adiacentRooms(ROOM2, ROOM1).");

				output.println();

				output.println("adiacentCells(POS1, POS2) :- cell(POS1), cell(POS2), POS1 = POS2 + 1.");
				output.println("adiacentCells(CELL1, CELL2) :- adiacentCells(CELL2, CELL1).");

				output.close();
				file.close();
			} catch (IOException e) {
				System.out
						.println("Error writing the general answer-set program \n"
								+ e);
			}

			is_as_written = true;
		}
	}

	public String exec(String subGoal) {
		String command = "";
		String plan = null;
			try {
				Runtime r = Runtime.getRuntime();
				command = "./dlv.bin as_program.dl general_planning.plan "
						+ "initial_plan_for_" + subGoal.toUpperCase()
						+ ".plan  -FP -silent";
				System.out.println(command);

				Process p = r.exec(command);

				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(p.getInputStream()));

				String s = bufferedReader.readLine();

				while (s != null) {
					plan += s + "\n";
					s = bufferedReader.readLine();
					if (s.isEmpty())
						s = null;
				}

				bufferedReader.close();
				p.destroy();
			} catch (Exception e) {
				System.out.println("ERRORE NELL'ESECUZIONE DEL COMANDO: "
						+ command);
			}
		return plan;
	}

	public LinkedList<String> getPlan(String command) {
		if (command == null)
			return null;

		String[] lines = command.split("\n");

		for (String line : lines) {
			if (line.startsWith("PLAN:")) {
				// ????
				String[] actions = line.substring(6).split(";");

				LinkedList<String> toReturn = new LinkedList<String>();

				for (String action : actions) {
					if (!action.trim().equals("(no action)")) {
						toReturn.add(action.trim());
						System.err.println(action.trim());
					}
				}
				return toReturn;
			}
		}
		return null;
	}
}